package com.sys.platform.common.utils;

import com.alibaba.fastjson2.JSONObject;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;


@Slf4j
public class HttpUtils {
    public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");

    public static Response getRequest(String url, Headers headers) throws IOException {
        OkHttpClient client = new OkHttpClient();

        Request request = new Request.Builder()
                .url(url).headers(headers)
                .build();
        return client.newCall(request).execute();
    }

    public static Response getRequest(String url, Map<String, Object> param) throws IOException {
        OkHttpClient client = new OkHttpClient.Builder()
                .connectTimeout(300, TimeUnit.SECONDS)
                .callTimeout(300, TimeUnit.SECONDS)
                .pingInterval(5, TimeUnit.SECONDS)
                .readTimeout(300, TimeUnit.SECONDS)
                .writeTimeout(300, TimeUnit.SECONDS)
                .build();
        if (!param.isEmpty() && url.contains("?")) {
            throw new RuntimeException("get请求url错误");
        }
        if (!param.isEmpty()) {
            StringBuilder sb = new StringBuilder(url);
            sb.append("?");
            param.forEach((k, v) -> sb.append(k).append("=").append(EncodingUtil.encodeURIComponent(v.toString())).append("&"));
            sb.delete(sb.length() - 1, sb.length());
            url = sb.toString();
        }
        log.info("-------------OkhttpUtils.getRequest.url----------: " + url);
        Request request = new Request.Builder()
                .url(url)
                .build();
        return client.newCall(request).execute();
    }

    public static <T> T getRequest(String url, Map<String, Object> param, Class<T> cls) throws IOException {
        T result = JSONObject.parseObject(Objects.requireNonNull(getRequest(url, param).body()).string(), cls);
        log.info("请求{},入参{}，结果{}", url, JSONObject.toJSONString(param), JSONObject.toJSONString(result));
        return result;
    }

    public static <T> T getRequest(String url, Class<T> cls) throws IOException {
        return getRequest(url, new HashMap<>(), cls);
    }

    public static Response getRequest(String url) throws IOException {
        OkHttpClient client = new OkHttpClient();

        Request request = new Request.Builder()
                .url(url)
                .build();
        return client.newCall(request).execute();
    }

    public static Response postRequest(String url, FormBody.Builder form) throws IOException {
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
                .url(url)
                .post(form.build())
                .build();
        return client.newCall(request).execute();
    }

    public static Response postRequest(String url, MultipartBody.Builder form, Map<String, Object> param) throws IOException {
        OkHttpClient client = new OkHttpClient();
        if (!param.isEmpty() && url.contains("?")) {
            throw new RuntimeException("get请求url错误");
        }
        if (!param.isEmpty()) {
            StringBuilder sb = new StringBuilder(url);
            sb.append("?");
            param.forEach((k, v) -> sb.append(k).append("=").append(v).append("&"));
            sb.delete(sb.length() - 1, sb.length());
            url = sb.toString();
        }
        Request request = new Request.Builder()
                .url(url)
                .post(form.build())
                .build();
        return client.newCall(request).execute();
    }

    public static Response postRequestJSONMap(String url, Map jsonMap) throws IOException {
        OkHttpClient client = new OkHttpClient();
        String param = JSONObject.toJSONString(jsonMap);
        RequestBody requestBody = RequestBody.create(JSON, param);
        Request request = new Request.Builder()
                .post(requestBody)
                .url(url)
                .build();
        return client.newCall(request).execute();
    }

    public static Response postRequestJSONString(String url, String jsonString) throws IOException {
        OkHttpClient client = new OkHttpClient();
        RequestBody requestBody = RequestBody.create(JSON, jsonString);
        Request request = new Request.Builder()
                .post(requestBody)
                .url(url)
                .build();
        return client.newCall(request).execute();
    }

    public static File downloadByUrl(String uri) {
        ReadableByteChannel readableByteChannel = null;
        FileChannel fileChannel = null;
        File file = null;
        URL url;
        FileOutputStream fileOutputStream = null;
        try {
            url = new URL(uri);
            //首先从 URL stream 中创建一个 ReadableByteChannel 来读取网络文件
            readableByteChannel = Channels.newChannel(url.openStream());
            String fileName = System.currentTimeMillis() + url.getPath().substring(url.getPath().lastIndexOf("."));
            String path = "/tmp" + "/" + fileName;
            file = new File(path);
            if (!file.getParentFile().exists() && !file.getParentFile().isDirectory()) {
                file.getParentFile().mkdirs();
            }
            //通过 ReadableByteChannel 读取到的字节会流动到一个 FileChannel 中，然后再关联一个本地文件进行下载操作
            fileOutputStream = new FileOutputStream(file);
            fileChannel = fileOutputStream.getChannel();
            //最后用 transferFrom()方法就可以把 ReadableByteChannel 获取到的字节写入本地文件
            fileChannel.transferFrom(readableByteChannel, 0, Long.MAX_VALUE);
            return file;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("下载文件失败:" + e.getLocalizedMessage());
            log.error(uri);
            throw new RuntimeException("下载文件失败");
        } finally {
            try {
                if (null != readableByteChannel) {
                    readableByteChannel.close();
                }
                if (null != fileChannel) {
                    fileChannel.close();
                }
                if (null != fileOutputStream) {
                    fileOutputStream.close();
                }
            } catch (IOException e) {
                log.error(e.getMessage());
            }
        }
    }


    public static String getResponseCode302Url(String url){
        try {
//            response.setHeader("Access-Control-Allow-Origin", "*");
//            response.setHeader("Access-Control-Allow-Methods", "*");
//            response.setHeader("Access-Control-Allow-Headers", "Origin,Content-Type,Accept,token,X-Requested-With");
//            SslUtil.ignoreSsl();
            StringBuffer buffer = new StringBuffer();
            System.out.println("访问地址:" + url);
            //发送get请求
            URL serverUrl = new URL(url);
            HttpURLConnection conn = (HttpURLConnection) serverUrl.openConnection();
            conn.setRequestMethod("GET");
            //必须设置false，否则会自动redirect到重定向后的地址
            conn.setInstanceFollowRedirects(false);
            conn.addRequestProperty("Accept-Charset", "UTF-8;");
            conn.addRequestProperty("User-Agent", "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.2.8) Firefox/3.6.8");
            conn.addRequestProperty("Referer", "http://matols.com/");
            conn.connect();


            //判定是否会进行302重定向
            if (conn.getResponseCode() == 302) {
                //如果会重定向，保存302重定向地址，以及Cookies,然后重新发送请求(模拟请求)
                String location = conn.getHeaderField("Location");
                String cookies = conn.getHeaderField("Set-Cookie");

                serverUrl = new URL(location);
                conn = (HttpURLConnection) serverUrl.openConnection();
                conn.setRequestMethod("GET");
                conn.setRequestProperty("Cookie", cookies);
                conn.addRequestProperty("Accept-Charset", "UTF-8;");
                conn.addRequestProperty("User-Agent","Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.2.8) Firefox/3.6.8");
                conn.addRequestProperty("Referer", "http://matols.com/");
                conn.connect();
                System.out.println("跳转地址:" + location);

//                response.setStatus(302);
//                response.setHeader("Location", location);
            }
            //将返回的输入流转换成字符串
            InputStream inputStream = conn.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream,"utf-8");
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            String str = null;
            while ((str = bufferedReader.readLine()) != null) {
                buffer.append(str);
            }
            bufferedReader.close();
            inputStreamReader.close();
            // 释放资源
            inputStream.close();
            inputStream = null;
            System.out.println(buffer.toString());
            return buffer.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
